Skip to content

feat(res-to-affine): Phase 3 slice 3 — literal let→const translation (Refs #57)#484

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/pensive-fermi-JVCzu
May 31, 2026
Merged

feat(res-to-affine): Phase 3 slice 3 — literal let→const translation (Refs #57)#484
hyperpolymath merged 1 commit into
mainfrom
claude/pensive-fermi-JVCzu

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

What

Third slice of Phase 3 for the .res.affine migration assistant (#57). Extends --translate to module-level literal let bindings, lowering them to typed AffineScript const declarations (AffineScript has no module-level let — a top-level value binding is const name: Type = value;).

ReScript AffineScript
let answer = 42 const answer: Int = 42;
let pi = 3.14 const pi: Float = 3.14;
let greeting = "hi" const greeting: String = "hi";
let enabled = true const enabled: Bool = true;

How / conservatism

Only int/float/string/bool literals translate — their type is inferred and the resulting const type-checks standalone (a literal is a compile-time constant). Skipped (left as marker + quoted original, never a wrong const):

  • non-literal body — a call (Date.now()), a ref(...) (the mutable-global anti-pattern), etc.
  • destructuring pattern (let (a, b) = …) — not a plain identifier
  • exotic numbers — hex / octal / binary / signed / scientific / underscored (number forms limited to plain decimal int and D+.D+ float, to avoid a literal the AffineScript lexer might reject)

Walker-internal only (classify_number / translate_literal / translate_let_const + a let_declaration branch in collect_translations); Walker.translate / Emitter.emit_translation signatures unchanged.

Scope boundary (the remaining #57 items)

The guarantee is "every emitted form type-checks standalone", which bounds translation to self-contained top-level declarations. Two forms are out of that scope by construction, now documented in the README:

Verification (local, apt-bootstrapped toolchain)

Check Result
full dune build ✅ exit 0
dune runtest tools/res-to-affine/ ✅ 22/22 (4 new slice-3 cases) against pinned grammar 990214a
compiler oracle main.exe check on the generated consts Type checking passed
doc-truthing + no-extension-ts guards ✅ pass

No OCaml outside tools/res-to-affine/walker.ml; config/compiler jobs unaffected.

Refs #57

https://claude.ai/code/session_017T8SzHr2yXav8hm4Ho76Uw


Generated by Claude Code

…tion (Refs #57)

Extends --translate to module-level value bindings: `let <id> = <literal>`
becomes a typed AffineScript `const`, since AffineScript has no module-level
`let` (a top-level value binding is `const name: Type = value;`).

  let answer = 42      ->  const answer: Int = 42;
  let pi = 3.14        ->  const pi: Float = 3.14;
  let greeting = "hi"  ->  const greeting: String = "hi";
  let enabled = true   ->  const enabled: Bool = true;

Conservative: only int/float/string/bool literals (type inferred, const
type-checks standalone). A call body, a `ref(...)` mutable-global, a
destructuring pattern, or an exotic number (hex/signed/scientific/underscored)
is skipped — left as marker + quoted original, never a wrong const. Number
forms limited to plain decimal int and D+.D+ float.

Walker-internal (translate_literal / classify_number / translate_let_const +
a let_declaration branch in collect_translations); Walker.translate /
Emitter.emit_translation signatures unchanged.

Scope boundary documented: switch->match (an expression needing whole-function
translation of un-annotated ReScript fns) and qualified-path resolution stay
out of the "every emitted form type-checks" scope.

Verified locally with the apt-bootstrapped toolchain: full `dune build` exit 0;
22 res-to-affine walker tests green (4 new) against pinned grammar 990214a;
`main.exe check` on the generated consts returns Type checking passed.

Refs #57

https://claude.ai/code/session_017T8SzHr2yXav8hm4Ho76Uw
@hyperpolymath hyperpolymath marked this pull request as ready for review May 31, 2026 05:48
@hyperpolymath hyperpolymath merged commit ea8bef5 into main May 31, 2026
15 of 24 checks passed
@hyperpolymath hyperpolymath deleted the claude/pensive-fermi-JVCzu branch May 31, 2026 05:48
hyperpolymath added a commit that referenced this pull request May 31, 2026
…rms (Refs #488) (#490)

STATE.a2ml: dated note for Phase 3 slice 3 (#484), the #57 closure, and successor #488; last-updated 2026-05-31. .claude/settings.json: add git-workflow commands to the permission allowlist. Docs/config only, no code. Refs #57 #488.
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 83 issues detected

Severity Count
🔴 Critical 2
🟠 High 13
🟡 Medium 68

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action ons/checkout@v6\n    needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action land/setup-deno@v2\n    needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in affine-vscode-publish.yml",
    "type": "missing_timeout_minutes",
    "file": "affine-vscode-publish.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants